package com.jy.api;

import com.jy.api.dao.SystemExceptionDao;
import com.jy.api.domain.SystemException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@ControllerAdvice
public class ApplicationExceptionHandler {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SystemExceptionDao systemExceptionDao;

    /**
     * 所有异常报错
     *
     * @param ex
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = Exception.class)
    public ResponseEntity allExceptionHandler(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        if (ex instanceof MissingServletRequestParameterException) {
            return ResponseEntity.status(400).body("缺少请求参数");
        } else if (ex instanceof HttpMessageNotReadableException) {
            return ResponseEntity.status(400).body("参数解析失败：" + ex.getMessage());
        } else if (ex instanceof ServletException) {
            return ResponseEntity.status(400).body(ex.getMessage());
        } else if (ex instanceof IOException) {
            return ResponseEntity.status(503).body(ex.getMessage());
        } else {
            if (ex instanceof JpaSystemException) {
                Throwable cause = ex.getCause();
                while (null != cause) {
                    if (cause.getMessage().contains("Incorrect string value")) {
                        return ResponseEntity.status(400).body(String.format("您提交的内容包含数据库不支持编码：%s", cause.getMessage()));
                    }
                    cause = cause.getCause();
                }
            }

            ex.printStackTrace();
            redisTemplate.execute((RedisCallback) rs -> {
                byte[] key = ex.getClass().getSimpleName().getBytes();
                Boolean result = rs.setNX(key, "1".getBytes());
                if (result) {
                    rs.expire(key, 60);

                    String exception = errorTrackSpace(ex);
                    systemExceptionDao.save(new SystemException(exception));
                }
                return result;
            });
            return ResponseEntity.status(500).body(ex.getMessage());
        }
    }

    private String errorTrackSpace(Exception e) {
        StringBuffer sb = new StringBuffer();
        if (e != null) {
            for (StackTraceElement element : e.getStackTrace()) {
                sb.append("\r\n\t").append(element);
            }
        }
        return sb.length() == 0 ? null : sb.toString();
    }
}
